package XunChunCPU.EXE

import chisel3._
import XunChunCPU.Accelerator._
import chisel3.util._

// 乘法加速模块
class MulModule extends Module{
    val io = IO(new Bundle{
        val OpA = Input(UInt(32.W))
        val OpB = Input(UInt(32.W))
        val ans = Output(UInt(32.W))
    })
    val Ps = Wire(Vec(16,UInt(32.W)))
    val cs = Wire(Vec(16,Bool()))
    // 第一阶段，生成16个部分积
    val bc0 = Module(new BoothChooser())
    val bc1 = Module(new BoothChooser())
    val bc2 = Module(new BoothChooser())
    val bc3 = Module(new BoothChooser())
    val bc4 = Module(new BoothChooser())
    val bc5 = Module(new BoothChooser())
    val bc6 = Module(new BoothChooser())
    val bc7 = Module(new BoothChooser())
    val bc8 = Module(new BoothChooser())
    val bc9 = Module(new BoothChooser())
    val bc10 = Module(new BoothChooser())
    val bc11 = Module(new BoothChooser())
    val bc12 = Module(new BoothChooser())
    val bc13 = Module(new BoothChooser())
    val bc14 = Module(new BoothChooser())
    val bc15 = Module(new BoothChooser())

    bc0.io.X := io.OpA
    bc0.io.y := Cat(io.OpB(1,0),false.B)
    bc1.io.X := (io.OpA << 2)(31,0)
    bc1.io.y := io.OpB(3,1)
    bc2.io.X := (io.OpA << 4)(31,0)
    bc2.io.y := io.OpB(5,3)
    bc3.io.X := (io.OpA << 6)(31,0)
    bc3.io.y := io.OpB(7,5)
    bc4.io.X := (io.OpA << 8)(31,0)
    bc4.io.y := io.OpB(9,7)
    bc5.io.X := (io.OpA << 10)(31,0)
    bc5.io.y := io.OpB(11,9)
    bc6.io.X := (io.OpA << 12)(31,0)
    bc6.io.y := io.OpB(13,11)
    bc7.io.X := (io.OpA << 14)(31,0)
    bc7.io.y := io.OpB(15,13)
    bc8.io.X := (io.OpA << 16)(31,0)
    bc8.io.y := io.OpB(17,15)
    bc9.io.X := (io.OpA << 18)(31,0)
    bc9.io.y := io.OpB(19,17)
    bc10.io.X := (io.OpA << 20)(31,0)
    bc10.io.y := io.OpB(21,19)
    bc11.io.X := (io.OpA << 22)(31,0)
    bc11.io.y := io.OpB(23,21)
    bc12.io.X := (io.OpA << 24)(31,0)
    bc12.io.y := io.OpB(25,23)
    bc13.io.X := (io.OpA << 26)(31,0)
    bc13.io.y := io.OpB(27,25)
    bc14.io.X := (io.OpA << 28)(31,0)
    bc14.io.y := io.OpB(29,27)
    bc15.io.X := (io.OpA << 30)(31,0)
    bc15.io.y := io.OpB(31,29)

    // 部分积
    Ps(0) := bc0.io.P
    Ps(1) := bc1.io.P
    Ps(2) := bc2.io.P
    Ps(3) := bc3.io.P
    Ps(4) := bc4.io.P
    Ps(5) := bc5.io.P
    Ps(6) := bc6.io.P
    Ps(7) := bc7.io.P
    Ps(8) := bc8.io.P
    Ps(9) := bc9.io.P
    Ps(10) := bc10.io.P
    Ps(11) := bc11.io.P
    Ps(12) := bc12.io.P
    Ps(13) := bc13.io.P
    Ps(14) := bc14.io.P
    Ps(15) := bc15.io.P

    cs(0) := bc0.io.c
    cs(1) := bc1.io.c
    cs(2) := bc2.io.c
    cs(3) := bc3.io.c
    cs(4) := bc4.io.c
    cs(5) := bc5.io.c
    cs(6) := bc6.io.c
    cs(7) := bc7.io.c
    cs(8) := bc8.io.c
    cs(9) := bc9.io.c
    cs(10) := bc10.io.c
    cs(11) := bc11.io.c
    cs(12) := bc12.io.c
    cs(13) := bc13.io.c
    cs(14) := bc14.io.c
    cs(15) := bc15.io.c

    // 中间寄存器
    val PsReg = RegInit(VecInit(Seq.fill(16)(0.U(32.W))))
    val csReg = RegInit(VecInit(Seq.fill(16)(false.B)))
    PsReg := Ps
    csReg := cs

    // WallaceTree计算结果
    // 32位,每位一个WallaceTree
    val wt0 = Module(new WallaceTree16)
    val wt1 = Module(new WallaceTree16)
    val wt2 = Module(new WallaceTree16)
    val wt3 = Module(new WallaceTree16)
    val wt4 = Module(new WallaceTree16)
    val wt5 = Module(new WallaceTree16)
    val wt6 = Module(new WallaceTree16)
    val wt7 = Module(new WallaceTree16)
    val wt8 = Module(new WallaceTree16)
    val wt9 = Module(new WallaceTree16)
    val wt10 = Module(new WallaceTree16)
    val wt11 = Module(new WallaceTree16)
    val wt12 = Module(new WallaceTree16)
    val wt13 = Module(new WallaceTree16)
    val wt14 = Module(new WallaceTree16)
    val wt15 = Module(new WallaceTree16)
    val wt16 = Module(new WallaceTree16)
    val wt17 = Module(new WallaceTree16)
    val wt18 = Module(new WallaceTree16)
    val wt19 = Module(new WallaceTree16)
    val wt20 = Module(new WallaceTree16)
    val wt21 = Module(new WallaceTree16)
    val wt22 = Module(new WallaceTree16)
    val wt23 = Module(new WallaceTree16)
    val wt24 = Module(new WallaceTree16)
    val wt25 = Module(new WallaceTree16)
    val wt26 = Module(new WallaceTree16)
    val wt27 = Module(new WallaceTree16)
    val wt28 = Module(new WallaceTree16)
    val wt29 = Module(new WallaceTree16)
    val wt30 = Module(new WallaceTree16)
    val wt31 = Module(new WallaceTree16)

    val Ns = Wire(Vec(32,Vec(16,Bool())))   //  每个WallaceTree的N输入
    for(i <- 0 until 32){
        for(j <- 0 until 16){
            Ns(i)(j) := PsReg(j)(i)
        }
    }
    // WallaceTree的输入
    wt0.io.N := Cat(Ns(0)(15),Ns(0)(14),Ns(0)(13),Ns(0)(12),Ns(0)(11),Ns(0)(10),Ns(0)(9),Ns(0)(8),Ns(0)(7),Ns(0)(6),Ns(0)(5),Ns(0)(4),Ns(0)(3),Ns(0)(2),Ns(0)(1),Ns(0)(0))
    wt0.io.Cin(0) := csReg(0)      // cs(15)进入最终的A操作数的最后一位
    wt0.io.Cin(1) := csReg(1)
    wt0.io.Cin(2) := csReg(2)
    wt0.io.Cin(3) := csReg(3)
    wt0.io.Cin(4) := csReg(4)
    wt0.io.Cin(5) := csReg(5)
    wt0.io.Cin(6) := csReg(6)
    wt0.io.Cin(7) := csReg(7)
    wt0.io.Cin(8) := csReg(8)
    wt0.io.Cin(9) := csReg(9)
    wt0.io.Cin(10) := csReg(10)
    wt0.io.Cin(11) := csReg(11)
    wt0.io.Cin(12) := csReg(12)
    wt0.io.Cin(13) := csReg(13)
    wt0.io.Cin(14) := csReg(14)
    wt1.io.N := Cat(Ns(1)(15),Ns(1)(14),Ns(1)(13),Ns(1)(12),Ns(1)(11),Ns(1)(10),Ns(1)(9),Ns(1)(8),Ns(1)(7),Ns(1)(6),Ns(1)(5),Ns(1)(4),Ns(1)(3),Ns(1)(2),Ns(1)(1),Ns(1)(0))
    wt1.io.Cin := wt0.io.Cout
    wt2.io.N := Cat(Ns(2)(15),Ns(2)(14),Ns(2)(13),Ns(2)(12),Ns(2)(11),Ns(2)(10),Ns(2)(9),Ns(2)(8),Ns(2)(7),Ns(2)(6),Ns(2)(5),Ns(2)(4),Ns(2)(3),Ns(2)(2),Ns(2)(1),Ns(2)(0))
    wt2.io.Cin := wt1.io.Cout
    wt3.io.N := Cat(Ns(3)(15),Ns(3)(14),Ns(3)(13),Ns(3)(12),Ns(3)(11),Ns(3)(10),Ns(3)(9),Ns(3)(8),Ns(3)(7),Ns(3)(6),Ns(3)(5),Ns(3)(4),Ns(3)(3),Ns(3)(2),Ns(3)(1),Ns(3)(0))
    wt3.io.Cin := wt2.io.Cout
    wt4.io.N := Cat(Ns(4)(15),Ns(4)(14),Ns(4)(13),Ns(4)(12),Ns(4)(11),Ns(4)(10),Ns(4)(9),Ns(4)(8),Ns(4)(7),Ns(4)(6),Ns(4)(5),Ns(4)(4),Ns(4)(3),Ns(4)(2),Ns(4)(1),Ns(4)(0))
    wt4.io.Cin := wt3.io.Cout
    wt5.io.N := Cat(Ns(5)(15),Ns(5)(14),Ns(5)(13),Ns(5)(12),Ns(5)(11),Ns(5)(10),Ns(5)(9),Ns(5)(8),Ns(5)(7),Ns(5)(6),Ns(5)(5),Ns(5)(4),Ns(5)(3),Ns(5)(2),Ns(5)(1),Ns(5)(0))
    wt5.io.Cin := wt4.io.Cout
    wt6.io.N := Cat(Ns(6)(15),Ns(6)(14),Ns(6)(13),Ns(6)(12),Ns(6)(11),Ns(6)(10),Ns(6)(9),Ns(6)(8),Ns(6)(7),Ns(6)(6),Ns(6)(5),Ns(6)(4),Ns(6)(3),Ns(6)(2),Ns(6)(1),Ns(6)(0))
    wt6.io.Cin := wt5.io.Cout
    wt7.io.N := Cat(Ns(7)(15),Ns(7)(14),Ns(7)(13),Ns(7)(12),Ns(7)(11),Ns(7)(10),Ns(7)(9),Ns(7)(8),Ns(7)(7),Ns(7)(6),Ns(7)(5),Ns(7)(4),Ns(7)(3),Ns(7)(2),Ns(7)(1),Ns(7)(0))
    wt7.io.Cin := wt6.io.Cout
    wt8.io.N := Cat(Ns(8)(15),Ns(8)(14),Ns(8)(13),Ns(8)(12),Ns(8)(11),Ns(8)(10),Ns(8)(9),Ns(8)(8),Ns(8)(7),Ns(8)(6),Ns(8)(5),Ns(8)(4),Ns(8)(3),Ns(8)(2),Ns(8)(1),Ns(8)(0))
    wt8.io.Cin := wt7.io.Cout
    wt9.io.N := Cat(Ns(9)(15),Ns(9)(14),Ns(9)(13),Ns(9)(12),Ns(9)(11),Ns(9)(10),Ns(9)(9),Ns(9)(8),Ns(9)(7),Ns(9)(6),Ns(9)(5),Ns(9)(4),Ns(9)(3),Ns(9)(2),Ns(9)(1),Ns(9)(0))
    wt9.io.Cin := wt8.io.Cout
    wt10.io.N := Cat(Ns(10)(15),Ns(10)(14),Ns(10)(13),Ns(10)(12),Ns(10)(11),Ns(10)(10),Ns(10)(9),Ns(10)(8),Ns(10)(7),Ns(10)(6),Ns(10)(5),Ns(10)(4),Ns(10)(3),Ns(10)(2),Ns(10)(1),Ns(10)(0))
    wt10.io.Cin := wt9.io.Cout
    wt11.io.N := Cat(Ns(11)(15),Ns(11)(14),Ns(11)(13),Ns(11)(12),Ns(11)(11),Ns(11)(10),Ns(11)(9),Ns(11)(8),Ns(11)(7),Ns(11)(6),Ns(11)(5),Ns(11)(4),Ns(11)(3),Ns(11)(2),Ns(11)(1),Ns(11)(0))
    wt11.io.Cin := wt10.io.Cout
    wt12.io.N := Cat(Ns(12)(15),Ns(12)(14),Ns(12)(13),Ns(12)(12),Ns(12)(11),Ns(12)(10),Ns(12)(9),Ns(12)(8),Ns(12)(7),Ns(12)(6),Ns(12)(5),Ns(12)(4),Ns(12)(3),Ns(12)(2),Ns(12)(1),Ns(12)(0))
    wt12.io.Cin := wt11.io.Cout
    wt13.io.N := Cat(Ns(13)(15),Ns(13)(14),Ns(13)(13),Ns(13)(12),Ns(13)(11),Ns(13)(10),Ns(13)(9),Ns(13)(8),Ns(13)(7),Ns(13)(6),Ns(13)(5),Ns(13)(4),Ns(13)(3),Ns(13)(2),Ns(13)(1),Ns(13)(0))
    wt13.io.Cin := wt12.io.Cout
    wt14.io.N := Cat(Ns(14)(15),Ns(14)(14),Ns(14)(13),Ns(14)(12),Ns(14)(11),Ns(14)(10),Ns(14)(9),Ns(14)(8),Ns(14)(7),Ns(14)(6),Ns(14)(5),Ns(14)(4),Ns(14)(3),Ns(14)(2),Ns(14)(1),Ns(14)(0))
    wt14.io.Cin := wt13.io.Cout
    wt15.io.N := Cat(Ns(15)(15),Ns(15)(14),Ns(15)(13),Ns(15)(12),Ns(15)(11),Ns(15)(10),Ns(15)(9),Ns(15)(8),Ns(15)(7),Ns(15)(6),Ns(15)(5),Ns(15)(4),Ns(15)(3),Ns(15)(2),Ns(15)(1),Ns(15)(0))
    wt15.io.Cin := wt14.io.Cout
    wt16.io.N := Cat(Ns(16)(15),Ns(16)(14),Ns(16)(13),Ns(16)(12),Ns(16)(11),Ns(16)(10),Ns(16)(9),Ns(16)(8),Ns(16)(7),Ns(16)(6),Ns(16)(5),Ns(16)(4),Ns(16)(3),Ns(16)(2),Ns(16)(1),Ns(16)(0))
    wt16.io.Cin := wt15.io.Cout
    wt17.io.N := Cat(Ns(17)(15),Ns(17)(14),Ns(17)(13),Ns(17)(12),Ns(17)(11),Ns(17)(10),Ns(17)(9),Ns(17)(8),Ns(17)(7),Ns(17)(6),Ns(17)(5),Ns(17)(4),Ns(17)(3),Ns(17)(2),Ns(17)(1),Ns(17)(0))
    wt17.io.Cin := wt16.io.Cout
    wt18.io.N := Cat(Ns(18)(15),Ns(18)(14),Ns(18)(13),Ns(18)(12),Ns(18)(11),Ns(18)(10),Ns(18)(9),Ns(18)(8),Ns(18)(7),Ns(18)(6),Ns(18)(5),Ns(18)(4),Ns(18)(3),Ns(18)(2),Ns(18)(1),Ns(18)(0))
    wt18.io.Cin := wt17.io.Cout
    wt19.io.N := Cat(Ns(19)(15),Ns(19)(14),Ns(19)(13),Ns(19)(12),Ns(19)(11),Ns(19)(10),Ns(19)(9),Ns(19)(8),Ns(19)(7),Ns(19)(6),Ns(19)(5),Ns(19)(4),Ns(19)(3),Ns(19)(2),Ns(19)(1),Ns(19)(0))
    wt19.io.Cin := wt18.io.Cout
    wt20.io.N := Cat(Ns(20)(15),Ns(20)(14),Ns(20)(13),Ns(20)(12),Ns(20)(11),Ns(20)(10),Ns(20)(9),Ns(20)(8),Ns(20)(7),Ns(20)(6),Ns(20)(5),Ns(20)(4),Ns(20)(3),Ns(20)(2),Ns(20)(1),Ns(20)(0))
    wt20.io.Cin := wt19.io.Cout
    wt21.io.N := Cat(Ns(21)(15),Ns(21)(14),Ns(21)(13),Ns(21)(12),Ns(21)(11),Ns(21)(10),Ns(21)(9),Ns(21)(8),Ns(21)(7),Ns(21)(6),Ns(21)(5),Ns(21)(4),Ns(21)(3),Ns(21)(2),Ns(21)(1),Ns(21)(0))
    wt21.io.Cin := wt20.io.Cout
    wt22.io.N := Cat(Ns(22)(15),Ns(22)(14),Ns(22)(13),Ns(22)(12),Ns(22)(11),Ns(22)(10),Ns(22)(9),Ns(22)(8),Ns(22)(7),Ns(22)(6),Ns(22)(5),Ns(22)(4),Ns(22)(3),Ns(22)(2),Ns(22)(1),Ns(22)(0))
    wt22.io.Cin := wt21.io.Cout
    wt23.io.N := Cat(Ns(23)(15),Ns(23)(14),Ns(23)(13),Ns(23)(12),Ns(23)(11),Ns(23)(10),Ns(23)(9),Ns(23)(8),Ns(23)(7),Ns(23)(6),Ns(23)(5),Ns(23)(4),Ns(23)(3),Ns(23)(2),Ns(23)(1),Ns(23)(0))
    wt23.io.Cin := wt22.io.Cout
    wt24.io.N := Cat(Ns(24)(15),Ns(24)(14),Ns(24)(13),Ns(24)(12),Ns(24)(11),Ns(24)(10),Ns(24)(9),Ns(24)(8),Ns(24)(7),Ns(24)(6),Ns(24)(5),Ns(24)(4),Ns(24)(3),Ns(24)(2),Ns(24)(1),Ns(24)(0))
    wt24.io.Cin := wt23.io.Cout
    wt25.io.N := Cat(Ns(25)(15),Ns(25)(14),Ns(25)(13),Ns(25)(12),Ns(25)(11),Ns(25)(10),Ns(25)(9),Ns(25)(8),Ns(25)(7),Ns(25)(6),Ns(25)(5),Ns(25)(4),Ns(25)(3),Ns(25)(2),Ns(25)(1),Ns(25)(0))
    wt25.io.Cin := wt24.io.Cout
    wt26.io.N := Cat(Ns(26)(15),Ns(26)(14),Ns(26)(13),Ns(26)(12),Ns(26)(11),Ns(26)(10),Ns(26)(9),Ns(26)(8),Ns(26)(7),Ns(26)(6),Ns(26)(5),Ns(26)(4),Ns(26)(3),Ns(26)(2),Ns(26)(1),Ns(26)(0))
    wt26.io.Cin := wt25.io.Cout
    wt27.io.N := Cat(Ns(27)(15),Ns(27)(14),Ns(27)(13),Ns(27)(12),Ns(27)(11),Ns(27)(10),Ns(27)(9),Ns(27)(8),Ns(27)(7),Ns(27)(6),Ns(27)(5),Ns(27)(4),Ns(27)(3),Ns(27)(2),Ns(27)(1),Ns(27)(0))
    wt27.io.Cin := wt26.io.Cout
    wt28.io.N := Cat(Ns(28)(15),Ns(28)(14),Ns(28)(13),Ns(28)(12),Ns(28)(11),Ns(28)(10),Ns(28)(9),Ns(28)(8),Ns(28)(7),Ns(28)(6),Ns(28)(5),Ns(28)(4),Ns(28)(3),Ns(28)(2),Ns(28)(1),Ns(28)(0))
    wt28.io.Cin := wt27.io.Cout
    wt29.io.N := Cat(Ns(29)(15),Ns(29)(14),Ns(29)(13),Ns(29)(12),Ns(29)(11),Ns(29)(10),Ns(29)(9),Ns(29)(8),Ns(29)(7),Ns(29)(6),Ns(29)(5),Ns(29)(4),Ns(29)(3),Ns(29)(2),Ns(29)(1),Ns(29)(0))
    wt29.io.Cin := wt28.io.Cout
    wt30.io.N := Cat(Ns(30)(15),Ns(30)(14),Ns(30)(13),Ns(30)(12),Ns(30)(11),Ns(30)(10),Ns(30)(9),Ns(30)(8),Ns(30)(7),Ns(30)(6),Ns(30)(5),Ns(30)(4),Ns(30)(3),Ns(30)(2),Ns(30)(1),Ns(30)(0))
    wt30.io.Cin := wt29.io.Cout
    wt31.io.N := Cat(Ns(31)(15),Ns(31)(14),Ns(31)(13),Ns(31)(12),Ns(31)(11),Ns(31)(10),Ns(31)(9),Ns(31)(8),Ns(31)(7),Ns(31)(6),Ns(31)(5),Ns(31)(4),Ns(31)(3),Ns(31)(2),Ns(31)(1),Ns(31)(0))
    wt31.io.Cin := wt30.io.Cout

    val A = Wire(Vec(32,Bool()))
    val B = Wire(Vec(32,Bool()))
    A(0) := csReg(15)
    A(1) := wt0.io.C
    A(2) := wt1.io.C
    A(3) := wt2.io.C
    A(4) := wt3.io.C
    A(5) := wt4.io.C
    A(6) := wt5.io.C
    A(7) := wt6.io.C
    A(8) := wt7.io.C
    A(9) := wt8.io.C
    A(10) := wt9.io.C
    A(11) := wt10.io.C
    A(12) := wt11.io.C
    A(13) := wt12.io.C
    A(14) := wt13.io.C
    A(15) := wt14.io.C
    A(16) := wt15.io.C
    A(17) := wt16.io.C
    A(18) := wt17.io.C
    A(19) := wt18.io.C
    A(20) := wt19.io.C
    A(21) := wt20.io.C
    A(22) := wt21.io.C
    A(23) := wt22.io.C
    A(24) := wt23.io.C
    A(25) := wt24.io.C
    A(26) := wt25.io.C
    A(27) := wt26.io.C
    A(28) := wt27.io.C
    A(29) := wt28.io.C
    A(30) := wt29.io.C
    A(31) := wt30.io.C
    // B操作数
    B(0) := wt0.io.S
    B(1) := wt1.io.S
    B(2) := wt2.io.S
    B(3) := wt3.io.S
    B(4) := wt4.io.S
    B(5) := wt5.io.S
    B(6) := wt6.io.S
    B(7) := wt7.io.S
    B(8) := wt8.io.S
    B(9) := wt9.io.S
    B(10) := wt10.io.S
    B(11) := wt11.io.S
    B(12) := wt12.io.S
    B(13) := wt13.io.S
    B(14) := wt14.io.S
    B(15) := wt15.io.S
    B(16) := wt16.io.S
    B(17) := wt17.io.S
    B(18) := wt18.io.S
    B(19) := wt19.io.S
    B(20) := wt20.io.S
    B(21) := wt21.io.S
    B(22) := wt22.io.S
    B(23) := wt23.io.S
    B(24) := wt24.io.S
    B(25) := wt25.io.S
    B(26) := wt26.io.S
    B(27) := wt27.io.S
    B(28) := wt28.io.S
    B(29) := wt29.io.S
    B(30) := wt30.io.S
    B(31) := wt31.io.S
    val trueA = Wire(UInt(32.W))
    val trueB = Wire(UInt(32.W))
    trueA := Cat(A(31),A(30),A(29),A(28),A(27),A(26),A(25),A(24),A(23),A(22),A(21),A(20),A(19),A(18),A(17),A(16),A(15),A(14),A(13),A(12),A(11),A(10),A(9),A(8),A(7),A(6),A(5),A(4),A(3),A(2),A(1),A(0))
    trueB := Cat(B(31),B(30),B(29),B(28),B(27),B(26),B(25),B(24),B(23),B(22),B(21),B(20),B(19),B(18),B(17),B(16),B(15),B(14),B(13),B(12),B(11),B(10),B(9),B(8),B(7),B(6),B(5),B(4),B(3),B(2),B(1),B(0))
    io.ans := trueA + trueB
}